﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.IO;

namespace Com.Guocz.Media.FileSystem.Crypt
{
    class RijndaelCrypt : ICrypt
    {
        private int keysize = 256;
        private ICryptoTransform decryptor;
        private ICryptoTransform encryptor;
        private string SHA1 = "SHA1";

        public byte[] Encrypt(byte[] clearData)
        {
            
            MemoryStream memoryStream = new MemoryStream();
            CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);

            cryptoStream.Write(clearData, 0, clearData.Length);
            cryptoStream.FlushFinalBlock();

            byte[] cipherTextBytes = memoryStream.ToArray();


            memoryStream.Close();
            cryptoStream.Close();

            Console.WriteLine("clear:" + clearData.Length + " cipher:" + cipherTextBytes.Length);
            return cipherTextBytes;
        }

        public byte[] Decrypt(byte[] cipherData)
        {
            MemoryStream memoryStream = new MemoryStream(cipherData);
            CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
            byte[] plainTextBytes = new byte[cipherData.Length];
            int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
            memoryStream.Close();
            cryptoStream.Close();

            byte[] result = new byte[decryptedByteCount];
            System.Array.Copy(plainTextBytes, result, result.Length);
            return result;
        }

        private string toLen16(string src)
        {
            return (src.Trim() + "GUOCZ_1984_02_25").Substring(0, 16);
        }

        public RijndaelCrypt(string name, string password)
        {
            byte[] initVectorBytes = Encoding.ASCII.GetBytes(toLen16(name));
            byte[] saltValueBytes = Encoding.ASCII.GetBytes("GUOCZ_1984_02_25");
            PasswordDeriveBytes pwd = new PasswordDeriveBytes(password, saltValueBytes, SHA1, 1);
            byte[] keyBytes = pwd.GetBytes(keysize / 8);
            RijndaelManaged symmetricKey = new RijndaelManaged();
            symmetricKey.Mode = CipherMode.CBC;

            decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
            encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
        }
    }
}
